package cn.vinann.demo.config;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import cn.vinann.demo.annotation.Desensitize;

/**
 * ResponseBody返回结果前处理
 * @author wn
 *
 */
@SuppressWarnings("rawtypes")
@ControllerAdvice("cn.vinann.demo.controller")
public class DemoResponseBodyAdvice implements ResponseBodyAdvice<Object>{

	@Override
	public Object beforeBodyWrite(Object obj, MethodParameter methodParameter, MediaType arg2,
			Class<? extends HttpMessageConverter<?>> arg3, ServerHttpRequest arg4, ServerHttpResponse arg5) {
		Desensitize desensitize = methodParameter.getMethodAnnotation(Desensitize.class);
		String[] strings = desensitize.excludes();
		List<String> excludes = Arrays.asList(strings);
		if(excludes.size()>0){
			try {
				if (obj instanceof List){
					List list = (List)obj;
					handleList(list,excludes);
					return list;
				}else{
					handleSingleObject(obj,excludes);
					return obj;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
        return obj;
	}

	@Override
	public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> arg1) {
		return methodParameter.getAnnotatedElement().isAnnotationPresent(Desensitize.class);
	}
	
	/**
     * 处理返回值是单个enity对象
     *
     * @param o
     * @return
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
     */
    private void handleSingleObject(Object o,List<String> excludes) throws IllegalArgumentException, IllegalAccessException{

        Field[] fields = o.getClass().getDeclaredFields();
        for (Field field:fields){
        	field.setAccessible(true);
        	String name = field.getName();
        	if(excludes.contains(name)){
        		field.set(o, "*****");
        	}
        }
    }

    /**
     * 处理返回值是列表
     *
     * @param list
     * @return
     * @throws IllegalAccessException 
     * @throws IllegalArgumentException 
     */
    private void handleList(List list,List<String> excludes) throws IllegalArgumentException, IllegalAccessException{
        for (Object o:list){
            handleSingleObject(o,excludes);
        }
    }

}
